package com.xinke.service.Impl;


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xinke.entity.EtcGantryTrafficData;
import com.xinke.entity.EtcSingleVehiclePass;
import com.xinke.entity.request.EtcGantryTrafficDataGroupDTO;
import com.xinke.entity.request.EtcGantryTrafficDataRequest;
import com.xinke.service.EtcGantryTrafficDataService;
import com.xinke.service.EtcSingleVehiclePassService;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


/**
 * 定时任务类
 */
@Component
@Slf4j
public class ETCInterfaceTask {
    private final RestTemplate restTemplate = new RestTemplate();
    private final ObjectMapper objectMapper = new ObjectMapper();
    // 转换器
    private ModelMapper modelMapper = new ModelMapper();
    /**
     * interface1的url地址
     */
    @Value("${etc.interface1.url}")
    private String interface1Url;
    /**
     * interface2的url地址
     */
    @Value("${etc.interface2.url}")
    private String interface2Url;
    /**
     * 证书
     */
    @Value("{etc.license}")
    private String license;
    /**
     * 需要查询的最晚的几条记录
     */
    @Value("${etc.interface1.lastedCount}")
    private int interface1LastedCount;

    @Autowired
    private EtcGantryTrafficDataService etcGantryTrafficDataService;
    @Autowired
    private EtcSingleVehiclePassService etcSingleVehiclePassService;


    /**
     * 类型转换方法
     *
     * @param data
     * @return
     */
    private EtcGantryTrafficDataRequest convertToRequest(EtcGantryTrafficData data) {
        return modelMapper.map(data, EtcGantryTrafficDataRequest.class);
    }

    /**
     * 定时任务
     */
    @Scheduled(fixedRate = 5 * 60 * 1000)
    public void callInterface1() {
        //从数据库中获取数据；使用mapper查询后，已经获得最早的数据和最新的数据
        List<EtcGantryTrafficDataGroupDTO> eList = getEtcGantryTrafficDataGroupDTO(interface1LastedCount);
        if (eList == null || eList.isEmpty()) {
            return;
        }
        //多线程发送请求
        sendMultiThread(eList, interface1Url);
    }

    /**
     * 多线程发请求
     */
    private void sendMultiThread(List<EtcGantryTrafficDataGroupDTO> dtoList, String url) {
        ExecutorService executor = Executors.newFixedThreadPool(8);
        for (EtcGantryTrafficDataGroupDTO dto : dtoList) {
            executor.submit(() -> {
                SendPostRequest(dto, url);
            });
        }
        //关闭任务提交
        executor.shutdown();
        //定时器启动5分钟检查
        ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
        scheduler.schedule(() -> {
                    if (!executor.isTerminated()) {
                        executor.shutdownNow();
                        System.out.println("线程池运行5min，自动关闭");
                    }
                    scheduler.shutdown();//关闭定时任务线程池
                }
                , 5, TimeUnit.MINUTES);
    }


    /**
     * 发送请求
     *
     * @param request
     * @param url
     * @return
     * @throws JsonProcessingException
     */
    private void SendPostRequest(EtcGantryTrafficDataGroupDTO request, String url)  {
        System.out.println(Thread.currentThread().getId() + ":发送请求");
        String message = null;
        List<Long> ids = request.getIds();
        try {
            //构造requestBody
            HashMap<String, Object> requestBody = new HashMap<>();
            //证书
            requestBody.put("license", license);
            //类型，默认为0
            requestBody.put("dataType", 0);
            requestBody.put("data", objectMapper.writeValueAsString(request.getEtcGantryTrafficDataRequest()));//发送数据
            //修改状态为上传成功
            etcGantryTrafficDataService.updateUploadByIds(ids, 1);
            //发送请求
            String response = restTemplate.postForObject(url, requestBody, String.class);
            Map<String, String> resultMap = objectMapper.readValue(response, Map.class);
            message = resultMap.get("message");
            String status = resultMap.get("status");
            if ("success".equals(status.trim())) {
                //修改状态为上传成功
                etcGantryTrafficDataService.updateUploadByIds(ids, 2, message, LocalDateTime.now());
            } else {
                //修改状态为上传失败
                etcGantryTrafficDataService.updateUploadByIds(ids, 3, message, 1);
            }
        } catch (Exception e) {
            e.printStackTrace();
            //修改状态为上传失败
            etcGantryTrafficDataService.updateUploadByIds(ids, 3, message, 1);
        }
    }


    /**
     * 返回结果对象集合
     *
     * @return
     */
    private List<EtcGantryTrafficDataGroupDTO> getEtcGantryTrafficDataGroupDTO(Integer lastedCount) {
//------------------------------------------------------------------------------------------------------------------------
       /* //版本1.0-使用QueryWrapper查询
        //1.构造查询条件
        QueryWrapper<EtcGantryTrafficData> qw = new QueryWrapper<>();
        qw.in("UPLOAD_STATUS", Arrays.asList(0, 3));
        //qw.gt("CREATE_TIME", LocalDateTime.now().minusMinutes(5));
        //版本是3以下
        qw.lt("UPLOAD_VERSION", 3);
        //根据时间顺序查询10条
        //2.查询结果
        List<EtcGantryTrafficData> originaQueryDataList = etcGantryTrafficDataService.list(qw);*/
//------------------------------------------------------------------------------------------------------------------------
        //版本1.1使用-mapper查询
        List<EtcGantryTrafficData> originaQueryDataList = etcGantryTrafficDataService.getUnUploadOrFailUploadDateLatestAndNewest(lastedCount);

        //结果判断
        if (originaQueryDataList.isEmpty()) {
            log.info("{}：集合为空", LocalDateTime.now());
            return null;
        }
        //结果封装
        List<EtcGantryTrafficDataGroupDTO> groupedDTOs = originaQueryDataList.stream().collect(Collectors.groupingBy(
                data -> new AbstractMap.SimpleEntry<>(
                        data.getGCRQ(),
                        data.getSJXH().intValue()
                )
        )).entrySet().stream().map(
                entry -> {
                    List<EtcGantryTrafficData> dataList = entry.getValue();
                    List<Long> ids = dataList.stream().map(EtcGantryTrafficData::getId).collect(Collectors.toList());
                    LocalDate gcrq = entry.getKey().getKey();
                    Integer sjxh = entry.getKey().getValue();
                    Integer uploadVersion = dataList.get(0).getUPLOAD_VERSION();
                    List<EtcGantryTrafficDataRequest> groupData = dataList.stream().map(this::convertToRequest).collect(Collectors.toList());
                    return new EtcGantryTrafficDataGroupDTO(ids, gcrq, sjxh, uploadVersion, groupData);
                }
        ).collect(Collectors.toList());
        //返回
        return groupedDTOs;
    }

    /**
     * 根据时间查询num条记录
     *
     * @param list
     * @return
     */
    private List<EtcGantryTrafficDataGroupDTO> getEtcSingleVehiclePassDTOLimit(List<EtcGantryTrafficDataGroupDTO> list, Integer num) {
        if (list == null || list.isEmpty()) {
            return null;
        }
        List<EtcGantryTrafficDataGroupDTO> sortedList = list.stream().sorted(
                Comparator.comparing(EtcGantryTrafficDataGroupDTO::getGcrq)
                        .thenComparing(EtcGantryTrafficDataGroupDTO::getSjxh)
        ).collect(Collectors.toList());

        ArrayList<EtcGantryTrafficDataGroupDTO> result = new ArrayList<>();
        int takeCount = Math.min(num, sortedList.size());
        result.addAll(sortedList.subList(0, takeCount));

        if (!sortedList.isEmpty()) {
            result.add(sortedList.get(sortedList.size() - 1));
        }

        return result;
    }

    /**
     * 单体数据查询
     */
    //@Scheduled(fixedRate = 5 * 60 * 1000)
    public void callInterface2() {
        try {
            EtcSingleVehiclePass etcSingleVehiclePass = etcSingleVehiclePassService.getOne(null);
            String requestBody = objectMapper.writeValueAsString(etcSingleVehiclePass);
            String response = restTemplate.patchForObject(interface1Url, requestBody, String.class);
            System.out.println("[接口2] 响应：" + response);

        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

    }

}
